﻿#region << 版 本 注 释 >>
/*----------------------------------------------------------------
// Copyright (C) 2021 kingerrobot
// 版权所有。 
//
// 文件名：WarehousingImpl
// 文件功能描述：入库任务生成
//
// 创建者：名字 (zzl)
// 时间：2021/12/14 15:13:13
//
// 修改人：
// 时间：
// 修改说明：
// 版本：V1.0.0
//----------------------------------------------------------------*/
#endregion


using KingerRobot.MexicoSailunMDC.Dao;
using System;
using System.Net.WebSockets;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static K8.CBB.XID;

namespace KingerRobot.MexicoSailunMDC.SpiService;
[Logging]
public class WarehousingImpl : IWarehousingService
{

    private readonly static ITask _Task = new BTask();
    private readonly static ITaskCmd _TaskCmd = new BTaskCmd();
    private readonly static IRcsLocation _RcsLocation = new BRcsLocation();
    private readonly static IProdMaterial _ProdMaterial = new BProdMaterial();
    private readonly static IWcsAsrsCrnInput _WcsAsrsCrnInput = new BWcsAsrsCrnInput();
    private readonly static IRcsEquipCrn _RcsEquipCrn = new BRcsEquipCrn();
    private readonly static IWarehousingBeforeService _BeforeWarehousingService = new WarehousingBeforeImpl();
    private readonly static IWmsSetting _WmsSetting = new BWmsSetting();
    private readonly static IProdSkuProduct _ProdSkuProduct = new BProdSkuProduct();
    private readonly static IProdProduct _ProdProduct = new BProdProduct();
    private readonly static IWms2MesService _Wms2MesService = new Wms2MesImpl();
    private readonly static IWcsEquipLocHold _WcsEquipLocHold = new BWcsEquipLocHold();


    //public void Main()
    //{
    //    var dbHelper = getDbHelper();
    //    finish_3_wcs_task(dbHelper);
    //}


    //private KingerRobot.k.DbHelper getDbHelper()
    //{
    //    var response = KingerRobot.RPC.Client.RpcHelper.Execute("KingerRobot.WanliMDC.Spi.SysDatabaseService,KingerRobot.WanliMDC.Spi", "GetDefaultDbConfig", null);
    //    var dbConfig = response.ServiceData.ServiceData.ToObject<KingerRobot.CBB.DbConfig>();
    //    var dbHelper = new KingerRobot.CBB.DbHelper(dbConfig);
    //    return dbHelper;
    //}

    //private void finish_3_wcs_task(KingerRobot.CBB.DbHelper dbHelper)
    //{
    //    dbHelper.CommandText = @"finish_3_wcs_task";
    //    dbHelper.CommandType = System.Data.CommandType.StoredProcedure;
    //    dbHelper.ClearParameters();
    //    dbHelper.ExecuteNonQuery();
    //}

    public void CreateTask()
    {

        WriteLog($"开始执行生成入库任务048", true);
        // 获取所有堆垛机 货叉，IsEnable 为：True 可用；False 不可用
        var crnForks = _RcsEquipCrn.GetUsableCrnFork();

        var crnIds = crnForks.Where(t => t.IsEnable == true)
            .Select(t => t.CrnId)
            .Distinct()
            .ToList(); // 有效堆垛机ID
        //WriteLog($"有效堆垛机crnIds,{crnIds.ToJson()}", true);
        List<Task> tasks = new List<Task>();

        var platformLocsTask = Task.Run(() =>
        {
            // 有货站台位
            return _WcsAsrsCrnInput.GetHasSkuLoc(crnIds);
        });
       
        //var platformAbnormalLocsTask = Task.Run(() =>
        //{
        //    // 异常口有货站台位
        //    return _WcsAsrsCrnAbnormalInput.GetHasSkuLoc(crnIds);
        //});

        var noGoodsLocsTask = Task.Run(() =>
        {
            // 获取所有空货位
            return _RcsLocation.GetNoGoodsLocation(crnForks);
        });


        // ( 秒)入库等待两个入库站台位都有货时长 此处不需多线程
        var wmsSetting = _WmsSetting.GetWmsSettingByCode(ConstFields.WarehousingTimeOut);
        _ = int.TryParse(wmsSetting?.Value, out var second);
        //var second = 600;

        WriteLog($"开始执行生成入库任务222", true);

        // 线体入库口；人工入库口；
        var platformHasLocs = platformLocsTask.Result;
        //WriteLog($"有货站台platformHasLocs,{platformHasLocs.Select(t=>t.CrnId).ToList().ToJson()}", true);
        //var platformAbnormalHasLocs = platformAbnormalLocsTask.Result;
        //platformHasLocs = platformHasLocs.Concat(platformAbnormalHasLocs).ToList();
        if (platformHasLocs is null || !platformHasLocs.Any())
        {
            WriteLog($"############入库站台位无货：{platformHasLocs.Count}", true);
            return;
        }


        var noGoodsLocs = noGoodsLocsTask.Result;
        if (noGoodsLocs is null || !noGoodsLocs.Any())
        {
            WriteLog($"############入库无空货位：{noGoodsLocs.Count}", true);
            return;
        }

        // 获取所有可用货叉
        foreach (var crn in crnIds)
        {
            WriteLog($"{crn}开始执行生成入库任务106", true);
            var forks = crnForks.Where(t => t.CrnId == crn && t.IsEnable == true).ToList();
            if (!forks.Any())
            {
                // OLDTODO【已完成】 在wcs_asrs_crn_input 表中增加 入库未生成入库任务原因字段 格式：内容+[时间]

                _WcsAsrsCrnInput.UpdateRemarkByCrnId(crn ?? 0, $"可用货叉未找到：{crn}[{DateTime.Now}]");
                // 无可用货叉返回
                continue;
            }
            WriteLog($"{crn}开始执行生成入库任务116", true);
            //此堆垛机持有的有货站台位置
            var haveLocs = platformHasLocs
                .Where(t => t.CrnId == crn && t.LocBindInfos.Count > 0)
                .OrderBy(t => t.MinTime)
                .ToList();
            WriteLog($"开始执行生成入库任务122", true);
            if (!haveLocs.Any())
            {
                WriteLog($"开始执行生成入库任务124", true);
                _WcsAsrsCrnInput.UpdateRemarkByCrnId(crn ?? 0, $"放胎位没有轮胎：{crn}[{DateTime.Now}]");
                // 站台位无货返回
                continue;
            }

            // 堆垛机站台位有货【线体入库口；人工入库口；】
            foreach (var haveLoc in haveLocs)
            {
                WriteLog($"{haveLoc.CrnId}开始执行生成入库任务134", true);
                LocationInfo tLocation1, tLocation2;
                LocBindInfo info1, info2;
                WriteLog($"{haveLoc.CrnId}开始执行生成入库任务137", true);
                // 一个堆垛机两头可入库，通过区域筛选一头 保证放胎位跟入库货位在一个局域
                var crnEmptyLoc = noGoodsLocs.Where(t => t.CrnId == crn && t.AreaId == haveLoc.AreaId).ToList();
                if (!crnEmptyLoc.Any())
                {
                    WriteLog($"{haveLoc.CrnId}开始执行生成入库任务141", true);
                    _WcsAsrsCrnInput.UpdateRemarkByCrnId(crn ?? 0, $"空库位未找到：{crn}[{DateTime.Now}]");
                    continue;
                }
                WriteLog($"{haveLoc.CrnId}开始执行生成入库任务146", true);
                // 绑定轮胎信息
                info1 = haveLoc.LocBindInfos.Where(t => t.Index == 1).FirstOrDefault();
                info2 = haveLoc.LocBindInfos.Where(t => t.Index == 2).FirstOrDefault();
                WriteLog($"{haveLoc.CrnId}开始执行生成入库任务147info1 is null---{info1 == null},info2 is null---{info2 == null}", true);
                var inType = (info1 ?? info2).InType;
                var direction = (info1 ?? info2).Direction;
                var areaId= (info1 ?? info2).AreaId;
                WriteLog($"{haveLoc.CrnId}开始执行生成入库任务152,intype{inType},dircetion{direction}", true);
                if (string.IsNullOrWhiteSpace(direction))
                {
                    WriteLog($"{haveLoc.CrnId}开始执行生成入库任务155", true);
                    _WcsAsrsCrnInput.UpdateRemarkByCrnId(crn ?? 0, $"{direction}未维护方向Direction：{crn}[{DateTime.Now}]");
                    continue;
                }
                WriteLog($"{haveLoc.CrnId}开始执行生成入库任务156", true);
                var inTypeName = inType == 0 ? "线体入库" : "人工入库";
                var topTire = direction.Equals(ConstFields.DirectionS) ? info2 : info1;
                WriteLog($"{haveLoc.CrnId}开始执行生成入库任务157", true);
                if (areaId == 10020301 && direction == ConstFields.DirectionS)
                {
                    WriteLog($"{haveLoc.CrnId}开始执行生成入库任务158", true);
                    topTire = info1;
                }
                WriteLog($"{haveLoc.CrnId}开始执行生成入库任务159,{topTire.LocId}", true);
                if (topTire is null) //  && inType == 0
                {
                    //WriteLog($"内侧取胎无胎a-{haveLoc.ToJson()},direction{direction}setting:{ConstFields.DirectionS}", true);
                    WriteLog($"{haveLoc.CrnId}内侧取胎无胎b-{inTypeName}-{info1?.LocId}-内测取胎位无胎无法执行：{crn}[{DateTime.Now}])");
                    //线体内测放胎位无胎返回
                    _WcsAsrsCrnInput.UpdateRemarkByCrnId(crn ?? 0, $"{inTypeName}-{info1?.LocId}-内测取胎位无胎无法执行：{crn}[{DateTime.Now}]");
                    continue;
                }
                WriteLog($"{haveLoc.CrnId} 开始执行生成入库任务170", true);
                // 货叉信息
                var fork1 = forks.Where(t => t.Index == 1 && t.IsEnable == true).FirstOrDefault();
                var fork2 = forks.Where(t => t.Index == 2 && t.IsEnable == true).FirstOrDefault();
                var forkSize = forks.Where(t => t.IsEnable == true).Count();
                WriteLog($"{haveLoc.CrnId}开始执行生成入库任务175,forksizeP{forkSize}", true);
                var flag = 0;
                if (forkSize == 0)
                {
                    WriteLog($"{haveLoc.CrnId}开始执行生成入库任务179", true);
                    _WcsAsrsCrnInput.UpdateRemarkByCrnId(crn ?? 0, $"{inTypeName}无可用货叉：{crn}[{DateTime.Now}]");
                    continue;
                }

                try
                {
                    var taskNos = string.Empty;
                    // forkSize 可用货叉数量 
                    //排除单叉的情况 必须双叉可用
                    if (forkSize == 2)
                    {
                        WriteLog($"{haveLoc.CrnId}开始执行生成入库任务191", true);
                        //if (info2 != null) [之前的判断方法]
                        //判断放胎位双胎有货
                        if (info1 != null && info2 != null)
                        {
                            WriteLog($"开始执行生成入库任务196", true);
                            if (info1.MaterialId == info2.MaterialId)
                            {
                                try
                                {
                                    // 过滤胎高跟大小胎
                                    //var emptylocs = GetLocHeight(crnEmptyLoc, info1.MaterialId.GetValueOrDefault());

                                    WriteLog($"开始执行生成入库任务202:{info1?.TaskNo}", true);
                                    // 物料相同（优先双空位——单空位相同物料——单空位不同物料）
                                    // fork1 执行 info1 货物；fork2 执行 info2 货物
                                    (tLocation1, tLocation2) = _RcsLocation.GetTagertDoubleLoc(crnEmptyLoc, info1.MaterialId, info2.MaterialId, fork1, fork2, info1.GroupId);//新加20270728

                                    if (tLocation1 is null || tLocation2 is null)
                                    {
                                        (tLocation2, tLocation1) = _RcsLocation.GetTagertDoubleLoc(crnEmptyLoc, info2.MaterialId, info1.MaterialId, fork2, fork1, info2.GroupId);//新加20270728
                                    }
                                    if (tLocation1 is null || tLocation2 is null)
                                    {
                                        _WcsAsrsCrnInput.UpdateRemarkByCrnId(crn ?? 0, $"{inTypeName}物料{info1.MaterialId}相同，空货位未找到：{tLocation1?.Id ?? 0}，{tLocation2?.Id ?? 0}[{DateTime.Now}]");

                                        continue;
                                    }

                                    //WriteLog($"222222222222222:{info1?.TaskNo}", true);
                                    // 防止乱库多加一层验证。
                                    var locFlag1 = _Task.GetHasTaskByTargetLoc(tLocation1?.Id ?? 0);
                                    var locFlag2 = _Task.GetHasTaskByTargetLoc(tLocation2?.Id ?? 0);

                                    //WriteLog($"3333333333333333:{info1?.TaskNo}", true);
                                    if (locFlag1 || locFlag2)
                                    {
                                        //if (locFlag1)
                                        //{
                                        //    _RcsLocation.ChangeLocEnable(tLocation1?.Id ?? 0, $"2物料{info1.MaterialId},选择库位有胎，禁用[{DateTime.Now}]");
                                        //}
                                        //if (locFlag2)
                                        //{
                                        //    _RcsLocation.ChangeLocEnable(tLocation2?.Id ?? 0, $"2物料{info2.MaterialId},选择库位有胎，禁用[{DateTime.Now}]");
                                        //}
                                        //_WcsAsrsCrnInput.UpdateRemarkByCrnId(crn ?? 0, $"{inTypeName}堆垛机2：{crn}——{(tLocation1?.Id ?? 0)} - " +
                                        //    $"{(tLocation2?.Id ?? 0)}--{crnEmptyLoc.Count}," +
                                        //    $" {info1.MaterialId}," +
                                        //    $" {info2.MaterialId}, {fork1.ToJson()}, {fork2.ToJson()}目标货位已占用[{DateTime.Now}]");
                                        WriteLog($"{inTypeName}堆垛机2：{crn}——{(tLocation1?.Id ?? 0)} - " +
                                            $"{(tLocation2?.Id ?? 0)}--{crnEmptyLoc.Count}," +
                                            $" {info1.MaterialId}," +
                                            $" {info2.MaterialId}, {fork1.ToJson()}, {fork2.ToJson()}目标货位已占用[{DateTime.Now}]", true);
                                        // 目标为有货，下一个循环
                                        continue;
                                    }

                                    //WriteLog($"44444444444444:{info1?.TaskNo}", true);

                                    //下面修改内容 lsq
                                    var groupNo = K8.LSF.Client.CodeValue(new DateTime(), "InGroupNo").ToInt(0);
                                    flag += EditTaskCreateCmd(tLocation1, fork1, info1, noGoodsLocs, groupNo, 1, (int)EnumTaskStatus.Create, ref taskNos);
                                    flag += EditTaskCreateCmd(tLocation2, fork2, info2, noGoodsLocs, groupNo, 2, (int)EnumTaskStatus.Create, ref taskNos);


                                    //WriteLog($"5555555555555:{info1?.TaskNo}", true);
                                    // 统一修改状态 可执行
                                    var num = _Task.UpdateTaskAndCmdStatusByTaskIds(new List<long>
                                  {
                                    info1?.TaskId ?? 0,
                                    info2?.TaskId ?? 0,
                                  }, (int)EnumTaskStatus.Executable);
                                }
                                catch (Exception ex)
                                {
                                    WriteLog($"开始执行生成入库任务异常:{ex.ToString()}", true);
                                }

                            }
                            else
                            {
                                // 物料不同（优先单空位相同物料——双空位——单空位不同物料）
                                // fork1 执行 info1 货物

                                // 过滤胎高跟大小胎
                                //var emptylocs = GetLocHeight(crnEmptyLoc, info1.MaterialId.GetValueOrDefault());

                                tLocation1 = _RcsLocation.GetTagertSingleLoc(crnEmptyLoc, info1.MaterialId, fork1, info1.GroupId);
                                // 删除占用(给下面语句使用)
                                crnEmptyLoc.Remove(crnEmptyLoc.Where(t => t.Id == tLocation1?.Id).FirstOrDefault());



                                //OLDTODO 判断是否有配对
                                var checkFlag = CheckSameGroupTask(info2.TaskId.GetValueOrDefault());

                                if (checkFlag == 0 || true) // 不同物料入不同库位
                                {

                                    // 过滤胎高跟大小胎
                                    _WcsAsrsCrnInput.UpdateRemarkByCrnId(crn ?? 0, $"{inTypeName}{crn}堆垛机，不配对物料，第二个胎没有配对{crnEmptyLoc.Count()},{crnEmptyLoc.Count()}[{DateTime.Now}]");
                                    //emptylocs = GetLocHeight(crnEmptyLoc, info2.MaterialId.GetValueOrDefault());
                                    // fork2 执行 info2 货物
                                    tLocation2 = _RcsLocation.GetTagertSingleLoc(crnEmptyLoc, info2.MaterialId, fork2,  info2.GroupId);

                                }
                                if (tLocation1 is null || tLocation2 is null)
                                {
                                    _WcsAsrsCrnInput.UpdateRemarkByCrnId(crn ?? 0, $"{inTypeName}物料{info1.MaterialId},{info2.MaterialId}不同，空货位未找到：{tLocation1?.Id ?? 0}，{tLocation2?.Id ?? 0}[{DateTime.Now}]");
                                    continue;
                                }

                                var locFlag1 = _Task.GetHasTaskByTargetLoc(tLocation1?.Id ?? 0);
                                var locFlag2 = _Task.GetHasTaskByTargetLoc(tLocation2?.Id ?? 0);
                                if (locFlag1 || locFlag2)
                                {
                                    if (locFlag1)
                                    {
                                        _RcsLocation.ChangeLocEnable(tLocation1?.Id ?? 0, $"3物料{info1.MaterialId},选择库位有胎，禁用[{DateTime.Now}]");
                                    }
                                    if (locFlag2)
                                    {
                                        _RcsLocation.ChangeLocEnable(tLocation2?.Id ?? 0, $"3物料{info2.MaterialId},选择库位有胎，禁用[{DateTime.Now}]");
                                    }
                                    _WcsAsrsCrnInput.UpdateRemarkByCrnId(crn ?? 0, $"{inTypeName}{tLocation1?.ToJson()} - {tLocation2?.ToJson()}目标货位已占用[{DateTime.Now}]");
                                    // 目标为有货，下一个循环
                                    continue;
                                }

                                //下面修改内容 lsq
                                var groupNo = K8.LSF.Client.CodeValue(new DateTime(), "InGroupNo").ToInt(0);
                                flag += EditTaskCreateCmd(tLocation1, fork1, info1, noGoodsLocs, groupNo, 1, (int)EnumTaskStatus.Create, ref taskNos);
                                flag += EditTaskCreateCmd(tLocation2, fork2, info2, noGoodsLocs, groupNo, 2, (int)EnumTaskStatus.Create, ref taskNos);

                                // 统一修改状态 可执行
                                var num = _Task.UpdateTaskAndCmdStatusByTaskIds(new List<long>
                        {
                            info1?.TaskId ?? 0,
                            info2?.TaskId ?? 0,
                        }, (int)EnumTaskStatus.Executable);
                            }

                        }
                        else//双叉可用的情况下  只有一个取货位有胎
                        {
                            WriteLog($"{haveLoc.CrnId}开始执行生成入库任务325", true);
                            var fork = fork1;
                            info1 = info1 ?? info2;
                            // 判断双胎单送时间判断
                            if (second > (DateTime.Now - info1.LocTime.GetValueOrDefault()).TotalSeconds)
                            {
                                continue;
                            }
                            WriteLog($"{haveLoc.CrnId}开始执行生成入库任务333", true);
                            // 获取执行货叉
                            if (info1.Index == 2)
                            {
                                fork = fork2;
                            }
                            WriteLog($"{haveLoc.CrnId}开始执行生成入库任务339,fork.index{info1.Index}", true);
                            ////判断单胎是否是出到异常口
                            //var targetLoc1 = _WcsAsrsCrnAbnormalOutPut.GetTargetAbnormalSingleLoc(info1.SkuId, fork, info1.Index);
                            //if (targetLoc1 != 0)
                            //{
                            //    tLocation1 = new LocationInfo()
                            //    {
                            //        Id = targetLoc1
                            //    };
                            //}
                            //else
                            //{
                            // 过滤胎高
                            //var emptylocs = GetLocHeight(crnEmptyLoc, info1.MaterialId.GetValueOrDefault());
                            // 对应货叉查找库位
                            tLocation1 = _RcsLocation.GetTagertSingleLoc(crnEmptyLoc, info1.MaterialId, fork, info1.GroupId);
                            WriteLog($"{haveLoc.CrnId}开始执行生成入库任务355", true);
                            if (tLocation1 is null && false)
                            {
                                // 替换货叉查找库位
                                fork = fork2;
                                if (info1.Index == 2)
                                {
                                    fork = fork1;
                                }
                                tLocation1 = _RcsLocation.GetTagertSingleLoc(crnEmptyLoc, info1.MaterialId, fork, info1.GroupId);
                            }
                            WriteLog($"{haveLoc.CrnId}开始执行生成入库任务366", true);
                            // 防止乱库多加一层验证。
                            var locFlag1 = _Task.GetHasTaskByTargetLoc(tLocation1?.Id ?? 0);
                            WriteLog($"{haveLoc.CrnId}开始执行生成入库任务369", true);
                            if (locFlag1)
                            {
                                WriteLog($"{haveLoc.CrnId}开始执行生成入库任务372", true);
                                if (locFlag1)
                                {
                                    WriteLog($"{haveLoc.CrnId}开始执行生成入库任务375", true);
                                    _RcsLocation.ChangeLocEnable(tLocation1?.Id ?? 0, $"4物料{info1.MaterialId},选择库位有胎，禁用[{DateTime.Now}]");
                                }
                                WriteLog($"{haveLoc.CrnId}开始执行生成入库任务378", true);
                                _WcsAsrsCrnInput.UpdateRemarkByCrnId(crn ?? 0, $"{inTypeName}堆垛机3：{crn}——{tLocation1?.Id ?? 0} - " +
                                    $" {crnEmptyLoc.Count},{crnEmptyLoc.Count}" +
                                    $" {info1?.MaterialId}," +
                                    $" {info2?.MaterialId}, {fork1.ToJson()}, {fork2.ToJson()}目标货位已占用[{DateTime.Now}]");
                                // 目标为有货，下一个循环
                                continue;
                            }
                            //}
                            WriteLog($"{haveLoc.CrnId}开始执行生成入库任务387", true);
                            //下面修改内容 lsq
                            var groupNo = K8.LSF.Client.CodeValue(new DateTime(), "InGroupNo").ToInt(0);
                            WriteLog($"{haveLoc.CrnId}开始执行生成入库任务390", true);
                            flag += EditTaskCreateCmd(tLocation1, fork, info1, noGoodsLocs, groupNo, 1, (int)EnumTaskStatus.Executable, ref taskNos);
                            //}
                            WriteLog($"{haveLoc.CrnId}开始执行生成入库任务393", true);
                        }
                    }

                    if (flag > 0)
                    {
                        _WcsAsrsCrnInput.UpdateRemarkByCrnId(crn ?? 0, $"{inTypeName}{crn}堆垛机,，任务{taskNos}创建{flag}成功[{DateTime.Now}]");
                    }
                    else
                    {
                        _WcsAsrsCrnInput.UpdateRemarkByCrnId(crn ?? 0, $"{inTypeName}{crn}堆垛机,，任务{taskNos}创建{flag}失败[{DateTime.Now}]");
                    }
                }
                catch (Exception ex)
                {
                    _WcsAsrsCrnInput.UpdateRemarkByCrnId(crn ?? 0, $"{inTypeName}：{ex.ToString()}：{crn}[{DateTime.Now}]");
                }
            }
        }

    }



    public int ExecuteTask(int taskNo, long locId)
    {
        var task = _Task.GetExecutableTaskByTaskNo(taskNo);
        if (task?.Id is not long taskId)
        {
            return 0;
        }
        var num = 0;
        try
        {
            num = _Task.UpdateTaskAndCmdStatus(locId, taskId, (int)EnumTaskStatus.Executed);

        }
        catch (Exception ex)
        {
            WriteLog($"堆垛机下发成功修改任务状态失败{ex.ToString()}", true);
            Thread.Sleep(1000);
            num = _Task.UpdateTaskAndCmdStatus(locId, taskId, (int)EnumTaskStatus.Executed);
        }
        finally
        {
            if (num > 0)
            {
                //OLDTODO 【已解决】添加 执行时位置改变 (0,因为绑定非本系统控制)
                _RcsLocation.UpdateLocationAndWcsLocWithSkuId(task.SkuId, 0, 0, true);
            }
        }
        return num;
    }

    public int FinishTask(int taskNo, long locId)
    {
        var result = 0;
        var task = _Task.GetExecutedByTaskNo(taskNo);
        //var task = _Task.GetTaskByTaskNo(taskNo);
        //var taskId = task?.Id ?? 0;
        if (task?.Id is not long taskId || task.TaskType != (int)EnumTaskType.Warehousing)
        {
            return 0;
        }
        WriteLog($"任务{taskNo}找到任务{taskId}", true);
        // 修改状态
        result = _Task.UpdateTaskAndCmdStatus(locId, taskId, (int)EnumTaskStatus.Finish);
        if (result == 0)
        {
            return 0;
        }
        WriteLog($"任务{taskNo}修改状态正常", true);
        // 修改货位标识
        var result1 = _RcsLocation.UpdateLocationAndWcsLocWithSkuId(task?.SkuId, 0, task.TargetLoc, true);
        //if (result == 0)
        //{
        //    return 0;
        //}
        WriteLog($"任务{taskNo}修改货位标识正常-{result1}", true);
        // 备份删除
        result = _Task.BakAndDeleteTaskAndCmd(taskId);
        try
        {
            WriteLog($"任务{taskNo}开始同步入库sku-{task.SkuId ?? 0},TargetLoc-{task.TargetLoc ?? 0}", true);
            //同步MES
            SyncMes(task.SkuId ?? 0, task.TargetLoc ?? 0);
        }
        catch (Exception ex)
        {
            WriteLog($"推送异常{ex.ToString()}", true);
        }
        if (result == 0)
        {
            return 0;
        }



        return result;
    }


    public int FinishTestTask(int taskNo, long locId)
    {
        var result = 0;
        var task = _Task.GetExecutedByTaskNo(taskNo);
        //var task = _Task.GetTaskByTaskNo(taskNo);
        var taskId = task?.Id ?? 0;
        if (task.TaskType == (int)EnumTaskType.Warehousing)
        {
            //入库任务完成反馈
            WriteLog($"任务{taskNo}找到任务{taskId}", true);
            // 修改状态
            result = _Task.UpdateTaskAndCmdStatus(locId, taskId, (int)EnumTaskStatus.Create);
            //获取当前任务组号
            var taskGroup = task.TaskGroup ?? 0;
            //获取当前库位组号
            var targetLoc = _RcsLocation.GetLocationById(task.TargetLoc ?? 0);
            var groupId = targetLoc.GroupId;
            var groupIndex = targetLoc.GroupIndex;
            //获取此堆垛机所有可入库库位
            var locs = _RcsLocation.GetLocationByCrnId(10030801);
            //获取此堆垛机可用入库的下一个组号
            var nextGroupId = locs.Select(t => t.GroupId).Distinct().OrderBy(t => t).Where(t => t > groupId).FirstOrDefault();
            //下次生成任务的库位
            var nextLoc = locs.Where(t => t.GroupId == nextGroupId && t.GroupIndex == groupIndex).FirstOrDefault();
            //修改任务目的地
            _Task.UpdateTaskAndCmdTargetLoc(taskId, nextLoc.Id ?? 0);
            // 修改货位标识
            _RcsLocation.UpdateTestInEnableRemark(task.TargetLoc ?? 0, "测试库位禁用入库");


            //获取此组号的入库任务是否全都重新生成完目的地
            var taskGroups = _Task.GetTasksByGroupNo(taskGroup);
            var count = taskGroups.Where(t => t.TaskStatus == (int)EnumTaskStatus.Create).Count();
            if (count >= 2)
            {
                //创建出库任务

                var outtargetLoc1 = 20030810102;

                var outtargetLoc2 = 20030810101;


                var outEquip1 = 10040801;
                var outEquip2 = 10040802;
                var groupNo = 100002;//;K8.LSF.Client.CodeValue(new DateTime(), "InGroupNo").ToInt(0);

                long startLoc1;
                long startLoc2;

                if (groupIndex == 1)
                {
                    startLoc1 = targetLoc.Id ?? 0;
                    startLoc2 = locs.Where(t => t.GroupId == groupId && t.GroupIndex == 2).FirstOrDefault()?.Id ?? 0;
                }
                else
                {
                    startLoc1 = locs.Where(t => t.GroupId == groupId && t.GroupIndex == 1).FirstOrDefault()?.Id ?? 0;
                    startLoc2 = targetLoc.Id ?? 0;
                }

                TaskDTO taskDTO1 = new TaskDTO()
                {
                    TaskId = XID.Nextval,
                    StartLoc = task.TargetLoc ?? 0,
                    TargetLoc = outtargetLoc1,
                    Type = (int)EnumTaskType.Exwarehouse,
                    Status = (int)EnumTaskStatus.Create,
                    SkuId = 1,
                    StartEquip = outEquip1,
                    TargetEquip = outEquip1,
                    GroupNo = groupNo,
                    GroupIndex = 1,
                };
                TaskDTO taskDTO2 = new TaskDTO()
                {
                    TaskId = XID.Nextval,
                    StartLoc = task.TargetLoc ?? 0,
                    TargetLoc = outtargetLoc2,
                    Type = (int)EnumTaskType.Exwarehouse,
                    Status = (int)EnumTaskStatus.Create,
                    SkuId = 1,
                    StartEquip = outEquip1,
                    TargetEquip = outEquip1,
                    GroupNo = groupNo,
                    GroupIndex = 1,
                };
                _Task.CreateTaskAndCmd(taskDTO1);
                _Task.CreateTaskAndCmd(taskDTO2);

            }



        }







        return result;
    }
    /// <summary>
    /// 同步MES
    /// </summary>
    /// <param name="skuId"></param>
    /// <param name="targetLoc"></param>
    private void SyncMes(long skuId, long targetLoc)
    {

        var mesService = K8.RSF.Client.Create<IMesService>();
        var location = _RcsLocation.GetLocationById(targetLoc);
        var tireBarcode = _ProdProduct.GetCodeBySkuId(skuId);
        mesService.AddInEndByBcdNos(tireBarcode, location?.LocCode ?? "");

    }



    [Obsolete("暂未启用", true)]
    public long CreateHaveTask(int taskNo)
    {
        //获取新的目标货位，修改任务目标货位，完成原有指令，生成新的指令
        if (taskNo == 0)
        {
            return 0;
        }
        var task = _Task.GetTaskByTaskNo(taskNo);
        if (task == null)
        {
            return 0;
        }
        var taskCmd = _TaskCmd.GetExecutableTaskCmdByTaskNo(task.TaskNo.GetValueOrDefault());
        if (taskCmd == null)
        {
            return 1;
        }
        var sku = _ProdSkuProduct.GetProdSkuProductBySkuId(task.SkuId);
        if (sku == null)
        {
            return 2;
        }
        //获取所有当前货叉可用的空货位
        var crnForks = _RcsEquipCrn.GetUsableCrnFork().Where(x => x.Fork == task.CurrentEquip);
        crnForks.FirstOrDefault().IsEnable = true;
        //去除原有指令的目标货位
        var noGoodsLocs = _RcsLocation.GetNoGoodsLocation(crnForks.ToList()).Where(t => t.Id != taskCmd.TargetLoc).ToList();
        var tLocation = _RcsLocation.GetTagertSingleLoc(noGoodsLocs, sku.MaterialId, crnForks.FirstOrDefault(), task.TaskGroup);
        if (tLocation == null)
        {
            //如果库位生成 入异常口任务
        }
        //添加新的指令 修改任务目标货位 修改原指令状态并删除备份
        _TaskCmd.UpdateTaskCmdStatus(taskCmd.TargetLoc.GetValueOrDefault(), task.Id.GetValueOrDefault(), (int)EnumTaskCmdStatus.Executed);

        _TaskCmd.BakAndDeleteCmd(task.Id.GetValueOrDefault());
        var cmd = _TaskCmd.CreateTaskCmd(new()
        {
            TaskId = task.Id,
            TaskNo = task.TaskNo,
            TaskType = task.TaskType,
            CurrentLoc = task.TargetLoc,
            TargetLoc = tLocation.Id,
            CmdStatus = (int)EnumTaskCmdStatus.Executable,
            CmdType = (int)EnumTaskType.Warehousing,
        });
        _Task.UpdateTaskTargetLoc(task.Id.GetValueOrDefault(), tLocation.Id.GetValueOrDefault(), task.MasterId.GetValueOrDefault(), task.SummaryId.GetValueOrDefault());
        //修改库位为异常???

        return cmd.Id.GetValueOrDefault();
    }

    public int CheckSameGroupTask(long taskId)
    {
        var task = _Task.GetExecutedTaskByTaskId(taskId);
        if (task == null)
        {
            return 0;
        }
        var taskList = _Task.GetTasksByGroupNo(task.TaskGroup.GetValueOrDefault());
        if (taskList.Count == 2)
        {
            var task2 = taskList.Where(t => t.Id != taskId).FirstOrDefault();
            if (task2.CreateTime >= task.CreateTime && task2.TaskType == (int)EnumTaskType.Transportation)
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }
        else
        {
            return 0;
        }

    }

    /// <summary>
    /// 修改原有的入库库位的目标位置 生成新的指令
    /// </summary>
    /// <param name="locationInfo"></param>
    /// <param name="crnForkInfo"></param>
    /// <param name="info"></param>
    /// <param name="noGoodsLocs"></param>
    /// <returns></returns>
    private int EditTaskCreateCmd(LocationInfo locationInfo,
      CrnForkInfo crnForkInfo,
      LocBindInfo info,
      List<LocationInfo> noGoodsLocs,
      int groupNo,
      int groupIndex,
      int status, ref string taskNos
      )
    {
        if (locationInfo == null)
        {
            return 0;
        }
        var inType = info.InType;
        var skuId = info.SkuId;
        var taskNo = info.TaskNo;
        var taskId = info.TaskId ?? 0;

        // 0：线体入库；1：手工入库
        if (inType == 0)
        {
            // 线体入库任务
            // 线体完成任务
            _BeforeWarehousingService.FinishTaskCmd(taskNo, info.LocId.GetValueOrDefault());
            // 修改任务；创建指令
            _Task.EditTaskAndCreateCmd(new()
            {
                TaskId = taskId,
                StartLoc = info.LocId.GetValueOrDefault(),
                TargetLoc = locationInfo.Id.GetValueOrDefault(),
                Type = (int)EnumTaskType.Warehousing,
                Status = status,
                SkuId = skuId,
                StartEquip = crnForkInfo.Fork,
                TargetEquip = crnForkInfo.Fork,
                GroupNo = groupNo,
                GroupIndex = groupIndex,
            });
        }
        else
        {
            // 清空绑定
            _RcsLocation.UpdateLocationNoGood(info.LocId);
            // 任务是否已创建
            var task = _Task.GetTaskBySkuId(skuId);
            if (task is not null)
            {
                return 0;
            }
            // 手工入库
            var taskBean = _Task.CreateTaskAndCmd(new()
            {
                TaskId = taskId,
                StartLoc = info.LocId.GetValueOrDefault(),
                TargetLoc = locationInfo.Id.GetValueOrDefault(),
                Type = (int)EnumTaskType.Warehousing,
                Status = status,
                SkuId = skuId,
                StartEquip = crnForkInfo.Fork,
                TargetEquip = crnForkInfo.Fork,
                GroupNo = groupNo,
                GroupIndex = groupIndex,
            });
            info.TaskId = taskBean?.POWcsTask.Id;
            info.TaskNo = taskBean?.POWcsTask.TaskNo ?? 0;
        }

        taskNos = $"{taskNos}|{taskNo}";
        // 删除空货位
        noGoodsLocs.Remove(locationInfo);
        // noGoodsLoc.Remove(noGoodsLoc.Where(t => t.Id == tLocation1.Id).FirstOrDefault());
        return 1;
    }


    void CreateAllLocTask(long crnId)
    {
        var haveLoc = _WcsAsrsCrnInput.GetWcsAsrsCrnInputsByEquipId(crnId);
        var info1 = haveLoc.InputLoc1;
        var info2 = haveLoc.InputLoc2;
        var direction = haveLoc.Direction;
        //_Task.gettaskby
        // 获取所有堆垛机 货叉，IsEnable 为：True 可用；False 不可用
        var crnForks = _RcsEquipCrn.GetUsableCrnFork().Where(t => t.CrnId == crnId).ToList();

        //获取所有空库位(入库可用)
        var noGoodsLocsTask = _RcsLocation.GetNoGoodsLocation(crnForks).OrderBy(t => t.GroupId);

        var locs = noGoodsLocsTask.Take(2).ToList();
        if (locs is null || locs.Count < 2)
        {
            return;
        }
        var loc1 = locs[1];
        var loc2 = locs[2];
        //组号一致 生成双叉任务
        if (loc1.GroupId == loc2.GroupId)
        {


        }


    }

}

